package com.msk.web.controller.basic;

import com.alibaba.fastjson2.JSONObject;
import com.msk.common.constant.Constants;
import com.msk.common.constant.UserConstants;
import com.msk.common.core.domain.AjaxResult;
import com.msk.common.core.domain.R;
import com.msk.common.core.domain.entity.SysRole;
import com.msk.common.core.domain.entity.SysUser;
import com.msk.common.core.domain.model.LoginUser;
import com.msk.common.core.redis.RedisCache;
import com.msk.common.exception.base.BaseException;
import com.msk.common.utils.AESUtils;
import com.msk.common.utils.DictUtils;
import com.msk.common.utils.SecurityUtils;
import com.msk.common.utils.StringUtils;
import com.msk.common.utils.spring.SpringUtils;
import com.msk.framework.web.service.SysApiRegisterService;
import com.msk.framework.web.service.SysMpLoginService;
import com.msk.framework.web.service.SysPermissionService;
import com.msk.framework.web.service.TokenService;
import com.msk.sys.domain.User;
import com.msk.sys.service.SystemService;
import com.msk.system.service.ISysRoleService;
import com.msk.system.service.ISysUserService;
import com.msk.third.service.MiniProgramService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * @desc: 小程序授权获取信息接口
 * @author: zlf
 * @date: 2022-02-28 15:29
 **/
@Api(tags = "小程序登录授权接口")
@RestController
@RequestMapping("/api/mp/miniProgram")
public class MiniProgramWxController {

    private static final Logger log = LoggerFactory.getLogger(MiniProgramWxController.class);

    @Autowired
    private MiniProgramService miniProgramService;

    @Autowired
    private SystemService systemService;

    @Autowired
    private SysApiRegisterService registerService;

    @Autowired
    private SysMpLoginService loginService;

    /**
     * 登录获取微信SessionKey接口
     *
     * @param code
     * @return
     */
    @ApiOperation("登录获取微信SessionKey接口")
    @PostMapping("/initWxLogin/{code}")
    public R<?> initWxLogin(@PathVariable("code") String code) {
        try {
            if (StringUtils.isEmpty(code)) {
                return R.appFail(2001, "授权code参数不能为空");
            }
            R<JSONObject> mpSessionKeyObj = miniProgramService.getMpSessionKey(code);
            return mpSessionKeyObj;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.appFail(2000, "授权登录失败");
    }

    /**
     * 同步生产环境的小程序token
     * @return
     */
    @ApiOperation("同步生产环境的小程序token")
    @PostMapping("/getAccessMpToken")
    public R<?> getAccessMpToken() {
        try {
            //获取缓存中的小程序token
            RedisCache redisService = SpringUtils.getBean(RedisCache.class);
            if (redisService.keyIsExists(Constants.SYS_CONFIG_KEY + "mp_access_token")) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("access_token", redisService.getCacheObject(Constants.SYS_CONFIG_KEY + "mp_access_token"));
                return R.appOk(jsonObject);
            }else{
                R<JSONObject> mpAccessToken = miniProgramService.getMpAccessToken();
                JSONObject jsonObject = mpAccessToken.getData();
                return R.appOk(jsonObject);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.appFail(2000, "小程序token失效");
    }

    @ApiOperation("登录获取微信手机号接口")
    @PostMapping("/getUserPhoneInfo/{code}")
    public R<?> getUserPhoneInfo(@PathVariable("code") String code) {
        try {
            if (StringUtils.isEmpty(code)) {
                return R.appFail(2001, "授权code参数不能为空");
            }
            R<JSONObject> mpPhoneNumberObj = miniProgramService.getMpPhoneNumber(code);
            return mpPhoneNumberObj;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.appFail(2000, "获取微信手机号失败");
    }

    /**
     * 解密小程序用户敏感数据
     *
     * @param params
     * @return
     */
    @ApiOperation("解密小程序用户敏感数据")
    @PostMapping("/decodeUserPhoneInfo")
    public R<?> decodeUserPhoneInfo(@RequestBody Map<String, String> params) {
        String code = params.get("code");
        String encryptedData = params.get("encryptedData");
        String iv = params.get("iv");
        String phoneNumber = params.get("phoneNumber");
        String userType = params.get("userType");
        if (StringUtils.isAnyEmpty(code, encryptedData, iv, phoneNumber, userType)) {
            return R.appFail(2001, "必须参数不能为空");
        }
        if (!"1".equals(userType) && !"2".equals(userType) && !"3".equals(userType)) {
            return R.appFail(2001, "身份类型错误");
        }
        try {
            String sessionKey = "";
            String openId = "";
            R<JSONObject> mpSessionKeyObj = miniProgramService.getMpSessionKey(code);
            if (mpSessionKeyObj.getCode() == Constants.SUCCESS_APP) {
                sessionKey = mpSessionKeyObj.getData().getString("session_key");
                openId = mpSessionKeyObj.getData().getString("openid");
            } else {
                return mpSessionKeyObj;
            }
            //调用AESUtils工具类decrypt方法解密获取json串
            byte[] resultByte = AESUtils.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey),
                    Base64.decodeBase64(iv));
            //判断返回参数是否为空
            if (null != resultByte && resultByte.length > 0) {
                String jsonResult = new String(resultByte, "UTF-8");
                JSONObject json = JSONObject.parseObject(jsonResult);
                json.putIfAbsent("openId", openId);
                //判断手机号有没有注册身份 如果没有注册则新增用户，如果有注册，则绑定openId
                // 查询用户信息
                User user = systemService.getByMobile(phoneNumber, userType);
                if (StringUtils.isNull(user)) {
                    user = new User();
                    user.setMobile(phoneNumber);
                    user.setUserIdentity(userType);
                    R<?> result = registerService.userRegister(user);
                    if (result.getCode() == Constants.SUCCESS_APP) {
                        json.putIfAbsent("token", result.getData());
                    } else {
                        return R.appFail(json, 2002,"一键登录失败");
                    }
                } else {
                    user.setOpenid(openId);
                    systemService.saveNewUser(user);
                    //手机号一键登录生成令牌
                    R<?> result = loginService.phoneMpLogin(user.getMobile(), openId, userType);
                    if (result.getCode() == Constants.SUCCESS_APP) {
                        json.putIfAbsent("token", result.getData());
                    } else {
                        return R.appFail(json, 2002,"一键登录失败");
                    }
                }
                return R.appOk(json, "获取信息成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.appFail(2000, "获取信息失败");
    }
}
